//**************************************************************
//					新人研修用ソースプログラム	
//**************************************************************
//ファイル名：practice11.c						
//**************************************************************

//===========================						
//インクルード
//===========================
#include "practice11_h.h"

//*********************************************************************
//機能名称　：メイン関数
//
//関数名　　：int main()
//引数　　　：なし
//戻り値　　：常に0
//機能　　　：年月の入力を促し、その月のカレンダーを表示する。
//*********************************************************************
int main(void){

	/* 構造体宣言 */
	struct calendar calendar1;
	
	/* 入力 */
	printf("西暦を入力してください。＞");
	scanf("%d", &calendar1.year);
	printf("月を入力してください。＞");
	scanf("%d", &calendar1.month);

	/* カレンダー計算・表示 */
	disp(calendar1);

	return 0;
}

//*********************************************************************
//機能名称　：カレンダー算出関数
//
//関数名　　：void calendar()
//引数　　　：int* days, int* week_day, struct calendar cal_culc
//戻り値　　：なし
//機能　　　：入力年月の最初の曜日を求め、ツェッラーの公式を使用し
//　　　　　：日数を計算する。
//*********************************************************************
void calendar(int* days, int* week_day, struct calendar cal_culc){
	
	/* 入力年year・入力月monthを作業用変数y,mに格納 */
	int y = cal_culc.year;		// ツェッラーの公式用year変数
	int m = cal_culc.month;		// ツェッラーの公式用month変数

    /* year年month月の最初の曜日を計算 */
    if (m <= 2){
		m += 12;
		y--;
	}
    *week_day = (y + (y / 4) - (y / 100) + (y / 400) + (((13 * m) + 8) / 5) + 1);
    *week_day = (*week_day) % 7;

    printf(" %d年%d月\n", cal_culc.year, cal_culc.month);
    printf(" 日 月 火 水 木 金 土\n");
    printf(" --------------------\n");

	/* 月の日数を計算 (ツェッラーの公式使用) */
    *days = month_d_array[(cal_culc.month) - 1];
    if(cal_culc.year % 4 == 0 && !(cal_culc.year % 100 == 0 && cal_culc.year % 400 != 0)){
		/* 閏年の場合 */
		if (cal_culc.month == 2){
			(*days)++;
		}
	}
}

//*********************************************************************
//機能名称　：カレンダー表示関数
//
//関数名　　：void disp()
//引数　　　：struct calendar cal_disp
//戻り値　　：なし
//機能　　　：日付けと曜日が合致するように体裁を整えてから
//　　　　　：カレンダーを表示する。
//*********************************************************************
void disp(struct calendar cal_disp){
	
	int days;		// 月の日数格納用ポインタ
	int i;			// ループ制御用変数
	int week_day;	// month月1日の曜日を格納するポインタ
	int d;			// 1～最終日数までカウントアップする変数

	/* 曜日計算 */
	calendar(&days, &week_day, cal_disp);

	/* 1日の位置まで空白で埋める */
	for(i = 0; i < (week_day); i++){
		printf("   ");
	}
	for(d = 1; d <= (days); d++){
		printf(" %2d", d);
		(week_day)++;
		/* 1週間分経過すれば、表示位置を先頭に戻す。 */
        if (week_day == 7){
			week_day = 0;
            printf("\n");
        }
	}
	/* 1週分で改行 */
	if(week_day != 0){
		printf("\n");
	}
}
